import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:image/image.dart' as img;
import 'dart:math' as math;

import 'package:path_provider/path_provider.dart';

enum ProcessMode {
  none, // 无效果
  bwLevel, // 黑白色阶
  colorLevel, // 多彩色阶
  bwDither, // 黑白抖动
  colorDither, // 多彩抖动
  colorDither2, // 多彩抖动2
  bwRedDither,    // 新增
  bwYellowDither, // 新增
  bwRedYellowDither // 新增
}

class EinkColor {
  final int r, g, b;
  const EinkColor(this.r, this.g, this.b);

  static const black = EinkColor(0, 0, 0);
  static const white = EinkColor(255, 255, 255);
  static const red = EinkColor(255, 0, 0);
  static const yellow = EinkColor(255, 255, 0);
  static const green = EinkColor(0, 255, 0);
  static const blue = EinkColor(0, 0, 255);
}

class EinkImageProcessor {

  static Future<String> processImage(
      String imagePath, ProcessMode processMode) async {
    if (!File(imagePath).existsSync() && !imagePath.startsWith('assets/')) {
      return imagePath;
    }

    if (File('${imagePath}_${processMode.name}_processed.png').existsSync()) {
      return '${imagePath}_${processMode.name}_processed.png';
    }

    // EasyLoading.show(status: '加载中...');

    img.Image? originalImage;
    if (imagePath.startsWith('assets/')) {
      final assetImage = await rootBundle.load(imagePath);
      final imageBytes = await assetImage.buffer.asUint8List();
      originalImage = img.decodeImage(imageBytes);
    } else {
      originalImage = await img.decodeImageFile(imagePath);
    }
    img.Image processedImage;

    if (originalImage == null) return imagePath;
    switch (processMode) {
      case ProcessMode.bwLevel:
        processedImage = await bwLevelProcess(originalImage);
        break;
      case ProcessMode.colorLevel:
        processedImage = await colorLevelProcess(originalImage);
        break;
      case ProcessMode.bwDither:
        processedImage = await bwDitherProcess(originalImage);
        break;
      case ProcessMode.colorDither:
        processedImage = await colorDitherProcess(originalImage);
        break;
      case ProcessMode.colorDither2:
        processedImage = await colorDitherProcess2(originalImage);
        break;
      case ProcessMode.bwRedDither:
        processedImage = await bwRedDitherProcess(originalImage);
        break;
      case ProcessMode.bwYellowDither:
        processedImage = await bwYellowDitherProcess(originalImage);
        break;
      case ProcessMode.bwRedYellowDither:
        processedImage = await bwRedYellowDitherProcess(originalImage);
        break;
      default:
        processedImage = originalImage;
    }
    final encodedImage = img.encodePng(processedImage);
    final cacheDir = await getApplicationCacheDirectory();
    final fileName =
        '${imagePath.split('/').last.split('.').first}_${processMode.name}_processed.png';
    final filePath = '${cacheDir.path}/$fileName';

    // Ensure the directory exists
    final directory = Directory(cacheDir.path);
    if (!await directory.exists()) {
      await directory.create(recursive: true);
    }

    final file = File(filePath);
    if (!await file.exists()) {
      await file.create();
    }

    // Process the image and write to file
    await file.writeAsBytes(encodedImage);

    // EasyLoading.dismiss();
    return file.path;
  }

  // 简化的颜色匹配算法
  static EinkColor _findClosestColor(int r, int g, int b, [int a = 255]) {
    // 标准化红色
    if (r > 180 && g < 50 && b < 50) {
      // 检测到红色范围
      // 计算需要的透明度来达到目标红色
      final targetR = 255;
      (a * r / targetR).round().clamp(0, 255);

      return EinkColor.red;
    }

    // 黄色判断条件
    if (r >= 255 && g >= 255 && b == 0) {
      return EinkColor.yellow;
    }

    // 白色判断条件
    if (r >= 255 && g >= 255 && b >= 255) {
      return EinkColor.white;
    }

    // 黑色判断条件
    if (r == 0 && g == 0 && b == 0) {
      return EinkColor.black;
    }

    // 如果不是完全匹配的颜色，使用最接近的
    final toYellow = math
        .sqrt(math.pow(r - 255, 2) + math.pow(g - 255, 2) + math.pow(b - 0, 2));
    final toRed = math
        .sqrt(math.pow(r - 255, 2) + math.pow(g - 0, 2) + math.pow(b - 0, 2));
    final toWhite = math.sqrt(
        math.pow(r - 255, 2) + math.pow(g - 255, 2) + math.pow(b - 255, 2));
    final toBlack =
        math.sqrt(math.pow(r - 0, 2) + math.pow(g - 0, 2) + math.pow(b - 0, 2));

    final minDistance =
        math.min(math.min(toYellow, toRed), math.min(toWhite, toBlack));

    if (minDistance == toYellow) return EinkColor.yellow;
    if (minDistance == toRed) return EinkColor.red;
    if (minDistance == toWhite) return EinkColor.white;
    return EinkColor.black;
  }

  static EinkColor _findClosestColor2(int r, int g, int b, [int a = 255]) {
    // 方案1：使用 HSL 色彩空间
    double getHue(int r, int g, int b) {
      final max = math.max(r, math.max(g, b));
      final min = math.min(r, math.min(g, b));
      final delta = max - min;

      if (delta == 0) return 0;

      double hue = 0;
      if (max == r) {
        hue = (g - b) / delta;
      } else if (max == g) {
        hue = 2 + (b - r) / delta;
      } else {
        hue = 4 + (r - g) / delta;
      }

      hue *= 60;
      if (hue < 0) hue += 360;
      return hue;
    }

    final hue = getHue(r, g, b);
    final max = math.max(r, math.max(g, b));
    final min = math.min(r, math.min(g, b));
    final lightness = (max + min) / 2;
    final saturation =
        max == min ? 0 : (max - min) / (255 - ((255 - (max - min)).abs()));

    // 黄色判断 - HSL方案
    if (hue >= 45 && hue <= 65 && saturation >= 0.2 && lightness >= 100) {
      return EinkColor.yellow;
    }

    // 方案2：RGB比例判断
    if (r > 200 && g > 200 && b < 100) {
      final rgRatio = r / g;
      if (rgRatio >= 0.8 && rgRatio <= 1.2) {
        // R和G的比例接近1
        return EinkColor.yellow;
      }
    }

    // 方案3：YUV色彩空间
    final y = 0.299 * r + 0.587 * g + 0.114 * b;
    final u = -0.14713 * r - 0.28886 * g + 0.436 * b;
    final v = 0.615 * r - 0.51499 * g - 0.10001 * b;

    // 黄色在YUV空间的特征
    if (y > 200 && u < 0 && v > 0) {
      return EinkColor.yellow;
    }

    // 方案4：加权距离计算
    final yellowDistance = math.sqrt(math.pow((r - 255) * 0.8, 2) + // 增加红色权重
            math.pow((g - 255) * 0.8, 2) + // 增加绿色权重
            math.pow(b * 1.2, 2) // 增加蓝色惩罚
        );

    if (yellowDistance < 150) {
      // 调整阈值
      return EinkColor.yellow;
    }

    // 红色判断
    if (r > 180 && g < 150 && b < 100) {
      return EinkColor.red;
    }

    // 黑白判断
    final brightness = (r * 0.299 + g * 0.587 + b * 0.114);
    return brightness < 128 ? EinkColor.black : EinkColor.white;
  }

  // 1. 黑白色阶处理
  static Future<img.Image> bwLevelProcess(img.Image source) async {
    final output = img.Image(
      width: source.width,
      height: source.height,
      numChannels: 3,
    );

    for (var y = 0; y < source.height; y++) {
      for (var x = 0; x < source.width; x++) {
        final pixel = source.getPixel(x, y);
        final gray =
            (pixel.r * 0.299 + pixel.g * 0.587 + pixel.b * 0.114).round();
        final value = gray < 128 ? 0 : 255;
        output.setPixelRgb(x, y, value, value, value);
      }
    }
    return Future.value(output);
  }

  // 2. 多彩色阶处理
  static Future<img.Image> colorLevelProcess(img.Image source) async {
    final numChannels = source.numChannels;
    final output = img.Image(
      width: source.width,
      height: source.height,
      numChannels: numChannels,
    );

    final pixels = source.getBytes();
    final outPixels = output.getBytes();

    for (var i = 0; i < pixels.length; i += numChannels) {
      if (i + 2 >= pixels.length) break;

      final r = pixels[i];
      final g = pixels[i + 1];
      final b = pixels[i + 2];
      final a = numChannels == 4 && i + 3 < pixels.length ? pixels[i + 3] : 255;

      // 对于红色进行特殊处理
      if (r > 180 && g < 50 && b < 50) {
        // 计算需要的透明度来达到目标红色
        final targetR = 255;
        final newAlpha = (a * r / targetR).round().clamp(0, 255);

        outPixels[i] = targetR; // R = 255
        outPixels[i + 1] = 0; // G = 0
        outPixels[i + 2] = 0; // B = 0
        if (numChannels == 4 && i + 3 < pixels.length) {
          outPixels[i + 3] = newAlpha; // 调整后的透明度
        }
      } else {
        // 其他颜色的正常处理
        final color = _findClosestColor2(r, g, b, a);
        outPixels[i] = color.r;
        outPixels[i + 1] = color.g;
        outPixels[i + 2] = color.b;
        if (numChannels == 4 && i + 3 < pixels.length) {
          outPixels[i + 3] = a;
        }
      }
    }

    return Future.value(output);
  }

  // 3. 黑白抖动处理
  static Future<img.Image> bwDitherProcess(img.Image source) async {
    final output = img.Image.from(source);
    final width = source.width;
    final height = source.height;

    for (var y = 0; y < height - 1; y++) {
      for (var x = 1; x < width - 1; x++) {
        final oldPixel = output.getPixel(x, y);
        final gray =
            (oldPixel.r * 0.299 + oldPixel.g * 0.587 + oldPixel.b * 0.114)
                .round();
        final newValue = gray < 128 ? 0 : 255;

        output.setPixelRgb(x, y, newValue, newValue, newValue);

        final error = gray - newValue;

        // Floyd-Steinberg扩散
        void distributeError(int px, int py, double factor) {
          final p = output.getPixel(px, py);
          final newGray =
              (p.r * 0.299 + p.g * 0.587 + p.b * 0.114 + error * factor)
                  .round();
          final value = newGray.clamp(0, 255);
          output.setPixelRgb(px, py, value, value, value);
        }

        distributeError(x + 1, y, 7 / 16); // 右
        distributeError(x - 1, y + 1, 3 / 16); // 左下
        distributeError(x, y + 1, 5 / 16); // 下
        distributeError(x + 1, y + 1, 1 / 16); // 右下
      }
    }
    return Future.value(output);
  }

  // 4. 多彩抖动处理
  static Future<img.Image> colorDitherProcess(img.Image source) async {
    final numChannels = source.numChannels;
    final output = img.Image(
      width: source.width,
      height: source.height,
      numChannels: numChannels,
    );

    final srcBytes = source.getBytes();
    final outBytes = output.getBytes();
    final width = source.width;
    final height = source.height;

    // 调整误差扩散矩阵的权重
    const matrix = [
      [0.0, 0.0, 0.0, 5.0 / 16.0], // 减小右边像素的误差权重
      [3.0 / 16.0, 5.0 / 16.0, 3.0 / 16.0, 0.0] // 增加下方像素的误差权重
    ];

    // 创建误差缓冲
    final errorsR = List.filled(width * 2, 0.0);
    final errorsG = List.filled(width * 2, 0.0);
    final errorsB = List.filled(width * 2, 0.0);

    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        final i = (y * width + x) * numChannels;

        if (i + 2 >= srcBytes.length) continue;

        // 获取像素值并添加误差
        var r = (srcBytes[i] + errorsR[x]).clamp(0.0, 255.0);
        var g = (srcBytes[i + 1] + errorsG[x]).clamp(0.0, 255.0);
        var b = (srcBytes[i + 2] + errorsB[x]).clamp(0.0, 255.0);

        // 调整阈值，减少白色倾向
        final brightness = (r * 0.299 + g * 0.587 + b * 0.114);
        final threshold = 128.0 + (brightness - 128.0) * 0.1; // 动态阈值

        // 找到最近的颜色
        final alpha = (i + 3 < srcBytes.length) ? srcBytes[i + 3] : 255;
        final newColor =
            _findClosestColor(r.toInt(), g.toInt(), b.toInt(), alpha);

        // 写入新颜色
        outBytes[i] = newColor.r;
        outBytes[i + 1] = newColor.g;
        outBytes[i + 2] = newColor.b;

        if (numChannels == 4 && i + 3 < srcBytes.length) {
          outBytes[i + 3] = srcBytes[i + 3];
        }

        // 计算误差并缩小误差范围
        final errorR = (r - newColor.r) * 0.8; // 减小误差传播
        final errorG = (g - newColor.g) * 0.8;
        final errorB = (b - newColor.b) * 0.8;

        // 扩散误差
        for (var dy = 0; dy < 2; dy++) {
          for (var dx = 0; dx < 4; dx++) {
            final factor = matrix[dy][dx];
            if (factor > 0) {
              final px = x + dx - 1;
              if (px >= 0 && px < width) {
                final idx = px + (dy == 0 ? 0 : width);
                errorsR[idx] += errorR * factor;
                errorsG[idx] += errorG * factor;
                errorsB[idx] += errorB * factor;
              }
            }
          }
        }
      }

      // 移动误差缓冲
      errorsR.setRange(0, width, errorsR.sublist(width));
      errorsG.setRange(0, width, errorsG.sublist(width));
      errorsB.setRange(0, width, errorsB.sublist(width));

      // 清除新行
      errorsR.fillRange(width, width * 2, 0.0);
      errorsG.fillRange(width, width * 2, 0.0);
      errorsB.fillRange(width, width * 2, 0.0);
    }

    return Future.value(output);
  }


  // 4. 多彩抖动处理
  static Future<img.Image> colorDitherProcess2(img.Image source) async {
    final numChannels = source.numChannels;
    final output = img.Image(
      width: source.width,
      height: source.height,
      numChannels: numChannels,
    );

    final srcBytes = source.getBytes();
    final outBytes = output.getBytes();
    final width = source.width;
    final height = source.height;

    // 调整误差扩散矩阵的权重
    const matrix = [
      [0.0, 0.0, 0.0, 5.0 / 16.0], // 减小右边像素的误差权重
      [3.0 / 16.0, 5.0 / 16.0, 3.0 / 16.0, 0.0] // 增加下方像素的误差权重
    ];

    // 创建误差缓冲
    final errorsR = List.filled(width * 2, 0.0);
    final errorsG = List.filled(width * 2, 0.0);
    final errorsB = List.filled(width * 2, 0.0);

    // 定义六种颜色
    final List<EinkColor> colors = [
      EinkColor.black,
      EinkColor.white,
      EinkColor.yellow,
      EinkColor.red,
      EinkColor.green, // 新增绿色
      EinkColor.blue   // 新增蓝色
    ];

    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        final i = (y * width + x) * numChannels;

        if (i + 2 >= srcBytes.length) continue;

        // 获取像素值并添加误差
        var r = (srcBytes[i] + errorsR[x]).clamp(0.0, 255.0);
        var g = (srcBytes[i + 1] + errorsG[x]).clamp(0.0, 255.0);
        var b = (srcBytes[i + 2] + errorsB[x]).clamp(0.0, 255.0);

        // 调整阈值，减少白色倾向
        final brightness = (r * 0.299 + g * 0.587 + b * 0.114);
        final threshold = 128.0 + (brightness - 128.0) * 0.1; // 动态阈值

        // 找到最近的颜色
        final alpha = (i + 3 < srcBytes.length) ? srcBytes[i + 3] : 255;
        final newColor = _findClosestColorToPalette(r.toInt(), g.toInt(), b.toInt(), alpha, colors);

        // 写入新颜色
        outBytes[i] = newColor.r;
        outBytes[i + 1] = newColor.g;
        outBytes[i + 2] = newColor.b;

        if (numChannels == 4 && i + 3 < srcBytes.length) {
          outBytes[i + 3] = srcBytes[i + 3];
        }

        // 计算误差并缩小误差范围
        final errorR = (r - newColor.r) * 0.8; // 减小误差传播
        final errorG = (g - newColor.g) * 0.8;
        final errorB = (b - newColor.b) * 0.8;

        // 扩散误差
        for (var dy = 0; dy < 2; dy++) {
          for (var dx = 0; dx < 4; dx++) {
            final factor = matrix[dy][dx];
            if (factor > 0) {
              final px = x + dx - 1;
              if (px >= 0 && px < width) {
                final idx = px + (dy == 0 ? 0 : width);
                errorsR[idx] += errorR * factor;
                errorsG[idx] += errorG * factor;
                errorsB[idx] += errorB * factor;
              }
            }
          }
        }
      }

      // 移动误差缓冲
      errorsR.setRange(0, width, errorsR.sublist(width));
      errorsG.setRange(0, width, errorsG.sublist(width));
      errorsB.setRange(0, width, errorsB.sublist(width));

      // 清除新行
      errorsR.fillRange(width, width * 2, 0.0);
      errorsG.fillRange(width, width * 2, 0.0);
      errorsB.fillRange(width, width * 2, 0.0);
    }

    return Future.value(output);
  }

  // 新增：找到最近的调色板颜色
  static EinkColor _findClosestColorToPalette(int r, int g, int b, int a, List<EinkColor> colors) {
    // 计算与每种颜色的距离并返回最近的颜色
    return colors.reduce((closest, color) {
      final distance = math.sqrt(math.pow(r - color.r, 2) + math.pow(g - color.g, 2) + math.pow(b - color.b, 2));
      final closestDistance = math.sqrt(math.pow(r - closest.r, 2) + math.pow(g - closest.g, 2) + math.pow(b - closest.b, 2));
      return distance < closestDistance ? color : closest;
    });
  }

  // 黑白红抖动
  static Future<img.Image> bwRedDitherProcess(img.Image source) async {
    final numChannels = source.numChannels;
    final output = img.Image(
      width: source.width,
      height: source.height,
      numChannels: numChannels,
    );

    final srcBytes = source.getBytes();
    final outBytes = output.getBytes();
    final width = source.width;
    final height = source.height;

    // 定义三种颜色
    final List<EinkColor> colors = [
      EinkColor.black,
      EinkColor.white,
      EinkColor.red,
    ];

    // 调整误差扩散矩阵的权重
    const matrix = [
      [0.0, 0.0, 0.0, 5.0 / 16.0], // 减小右边像素的误差权重
      [3.0 / 16.0, 5.0 / 16.0, 3.0 / 16.0, 0.0] // 增加下方像素的误差权重
    ];

    // 创建误差缓冲
    final errorsR = List.filled(width * 2, 0.0);
    final errorsG = List.filled(width * 2, 0.0);
    final errorsB = List.filled(width * 2, 0.0);

    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        final i = (y * width + x) * numChannels;

        if (i + 2 >= srcBytes.length) continue;

        // 获取像素值并添加误差
        var r = (srcBytes[i] + errorsR[x]).clamp(0.0, 255.0);
        var g = (srcBytes[i + 1] + errorsG[x]).clamp(0.0, 255.0);
        var b = (srcBytes[i + 2] + errorsB[x]).clamp(0.0, 255.0);

        // 调整阈值，减少白色倾向
        final brightness = (r * 0.299 + g * 0.587 + b * 0.114);
        final threshold = 128.0 + (brightness - 128.0) * 0.1; // 动态阈值

        // 找到最近的颜色
        final alpha = (i + 3 < srcBytes.length) ? srcBytes[i + 3] : 255;
        final newColor = _findClosestColorToPalette(r.toInt(), g.toInt(), b.toInt(), alpha, colors);

        // 写入新颜色
        outBytes[i] = newColor.r;
        outBytes[i + 1] = newColor.g;
        outBytes[i + 2] = newColor.b;

        if (numChannels == 4 && i + 3 < srcBytes.length) {
          outBytes[i + 3] = srcBytes[i + 3];
        }

        // 计算误差并缩小误差范围
        final errorR = (r - newColor.r) * 0.8; // 减小误差传播
        final errorG = (g - newColor.g) * 0.8;
        final errorB = (b - newColor.b) * 0.8;

        // 扩散误差
        for (var dy = 0; dy < 2; dy++) {
          for (var dx = 0; dx < 4; dx++) {
            final factor = matrix[dy][dx];
            if (factor > 0) {
              final px = x + dx - 1;
              if (px >= 0 && px < width) {
                final idx = px + (dy == 0 ? 0 : width);
                errorsR[idx] += errorR * factor;
                errorsG[idx] += errorG * factor;
                errorsB[idx] += errorB * factor;
              }
            }
          }
        }
      }

      // 移动误差缓冲
      errorsR.setRange(0, width, errorsR.sublist(width));
      errorsG.setRange(0, width, errorsG.sublist(width));
      errorsB.setRange(0, width, errorsB.sublist(width));

      // 清除新行
      errorsR.fillRange(width, width * 2, 0.0);
      errorsG.fillRange(width, width * 2, 0.0);
      errorsB.fillRange(width, width * 2, 0.0);
    }

    return Future.value(output);
  }

  // 黑白黄抖动
  static Future<img.Image> bwYellowDitherProcess(img.Image source) async {
    final numChannels = source.numChannels;
    final output = img.Image(
      width: source.width,
      height: source.height,
      numChannels: numChannels,
    );

    final srcBytes = source.getBytes();
    final outBytes = output.getBytes();
    final width = source.width;
    final height = source.height;

    // 定义三种颜色
    final List<EinkColor> colors = [
      EinkColor.black,
      EinkColor.white,
      EinkColor.yellow,
    ];

    // 调整误差扩散矩阵的权重
    const matrix = [
      [0.0, 0.0, 0.0, 5.0 / 16.0],
      [3.0 / 16.0, 5.0 / 16.0, 3.0 / 16.0, 0.0]
    ];

    // 创建误差缓冲
    final errorsR = List.filled(width * 2, 0.0);
    final errorsG = List.filled(width * 2, 0.0);
    final errorsB = List.filled(width * 2, 0.0);

    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        final i = (y * width + x) * numChannels;

        if (i + 2 >= srcBytes.length) continue;

        var r = (srcBytes[i] + errorsR[x]).clamp(0.0, 255.0);
        var g = (srcBytes[i + 1] + errorsG[x]).clamp(0.0, 255.0);
        var b = (srcBytes[i + 2] + errorsB[x]).clamp(0.0, 255.0);

        final brightness = (r * 0.299 + g * 0.587 + b * 0.114);
        final threshold = 128.0 + (brightness - 128.0) * 0.1;

        final alpha = (i + 3 < srcBytes.length) ? srcBytes[i + 3] : 255;
        final newColor = _findClosestColorToPalette(r.toInt(), g.toInt(), b.toInt(), alpha, colors);

        outBytes[i] = newColor.r;
        outBytes[i + 1] = newColor.g;
        outBytes[i + 2] = newColor.b;

        if (numChannels == 4 && i + 3 < srcBytes.length) {
          outBytes[i + 3] = srcBytes[i + 3];
        }

        final errorR = (r - newColor.r) * 0.8;
        final errorG = (g - newColor.g) * 0.8;
        final errorB = (b - newColor.b) * 0.8;

        for (var dy = 0; dy < 2; dy++) {
          for (var dx = 0; dx < 4; dx++) {
            final factor = matrix[dy][dx];
            if (factor > 0) {
              final px = x + dx - 1;
              if (px >= 0 && px < width) {
                final idx = px + (dy == 0 ? 0 : width);
                errorsR[idx] += errorR * factor;
                errorsG[idx] += errorG * factor;
                errorsB[idx] += errorB * factor;
              }
            }
          }
        }
      }

      errorsR.setRange(0, width, errorsR.sublist(width));
      errorsG.setRange(0, width, errorsG.sublist(width));
      errorsB.setRange(0, width, errorsB.sublist(width));

      errorsR.fillRange(width, width * 2, 0.0);
      errorsG.fillRange(width, width * 2, 0.0);
      errorsB.fillRange(width, width * 2, 0.0);
    }

    return Future.value(output);
  }

  // 黑白红黄抖动
  static Future<img.Image> bwRedYellowDitherProcess(img.Image source) async {
    final numChannels = source.numChannels;
    final output = img.Image(
      width: source.width,
      height: source.height,
      numChannels: numChannels,
    );

    final srcBytes = source.getBytes();
    final outBytes = output.getBytes();
    final width = source.width;
    final height = source.height;

    // 定义四种颜色
    final List<EinkColor> colors = [
      EinkColor.black,
      EinkColor.white,
      EinkColor.red,
      EinkColor.yellow,
    ];

    // 调整误差扩散矩阵的权重
    const matrix = [
      [0.0, 0.0, 0.0, 5.0 / 16.0],
      [3.0 / 16.0, 5.0 / 16.0, 3.0 / 16.0, 0.0]
    ];

    // 创建误差缓冲
    final errorsR = List.filled(width * 2, 0.0);
    final errorsG = List.filled(width * 2, 0.0);
    final errorsB = List.filled(width * 2, 0.0);

    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        final i = (y * width + x) * numChannels;

        if (i + 2 >= srcBytes.length) continue;

        var r = (srcBytes[i] + errorsR[x]).clamp(0.0, 255.0);
        var g = (srcBytes[i + 1] + errorsG[x]).clamp(0.0, 255.0);
        var b = (srcBytes[i + 2] + errorsB[x]).clamp(0.0, 255.0);

        final brightness = (r * 0.299 + g * 0.587 + b * 0.114);
        final threshold = 128.0 + (brightness - 128.0) * 0.1;

        final alpha = (i + 3 < srcBytes.length) ? srcBytes[i + 3] : 255;
        final newColor = _findClosestColorToPalette(r.toInt(), g.toInt(), b.toInt(), alpha, colors);

        outBytes[i] = newColor.r;
        outBytes[i + 1] = newColor.g;
        outBytes[i + 2] = newColor.b;

        if (numChannels == 4 && i + 3 < srcBytes.length) {
          outBytes[i + 3] = srcBytes[i + 3];
        }

        final errorR = (r - newColor.r) * 0.8;
        final errorG = (g - newColor.g) * 0.8;
        final errorB = (b - newColor.b) * 0.8;

        for (var dy = 0; dy < 2; dy++) {
          for (var dx = 0; dx < 4; dx++) {
            final factor = matrix[dy][dx];
            if (factor > 0) {
              final px = x + dx - 1;
              if (px >= 0 && px < width) {
                final idx = px + (dy == 0 ? 0 : width);
                errorsR[idx] += errorR * factor;
                errorsG[idx] += errorG * factor;
                errorsB[idx] += errorB * factor;
              }
            }
          }
        }
      }

      errorsR.setRange(0, width, errorsR.sublist(width));
      errorsG.setRange(0, width, errorsG.sublist(width));
      errorsB.setRange(0, width, errorsB.sublist(width));

      errorsR.fillRange(width, width * 2, 0.0);
      errorsG.fillRange(width, width * 2, 0.0);
      errorsB.fillRange(width, width * 2, 0.0);
    }

    return Future.value(output);
  }
}
